﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Utility2DLibrary
{
    public class Camera2D
    {
        protected Vector2 screenDimensions;
        public Vector2 ScreenDimensions
        {
            get { return this.screenDimensions; }
            set { this.screenDimensions = value; }
        }

        protected Vector2 position = Vector2.Zero;
        public Vector2 Position
        {
            get { return position; }
            set
            {
                position = value;
                visibleArea.X = position.X + offset.X - visibleArea.Width / 2;
                visibleArea.Y = position.Y + offset.Y - visibleArea.Height / 2;
            }
        }
        protected Vector2 offset = Vector2.Zero;
        public Vector2 Offset
        {
            get { return offset; }
            set
            {
                offset = value;
                visibleArea.X = position.X + offset.X - visibleArea.Width / 2;
                visibleArea.Y = position.Y + offset.Y - visibleArea.Height / 2;
            }
        }

        // RectangleF = a Rectangle class that uses floats instead of ints
        protected System.Drawing.RectangleF visibleArea;
        public System.Drawing.RectangleF VisibleArea
        {
            get { return visibleArea; }
        }

        public float ViewingWidth
        {
            get { return visibleArea.Width; }
            set { visibleArea.Width = value; }
        }

            public float ViewingHeight
        {
            get { return visibleArea.Height; }
            set { visibleArea.Height = value; }
        }
    
        protected float rotation = 0.0f;
        public float Rotation
        {
            get { return rotation; }
            set { rotation = value; }
        }

        // <0 - <1 = Zoom Out
        // >1 = Zoom In
        // <0 = Funky (flips axis)
        protected Vector2 zoom = Vector2.One;
        public Vector2 Zoom
        {
            get { return zoom; }
            set { zoom = value; }
        }

        public Vector2 ScreenPosition
        {
            get { return new Vector2(screenDimensions.X / 2, screenDimensions.Y / 2); }
        }

        public Camera2D(Vector2 MaxDimensions)
        {
            this.screenDimensions = MaxDimensions;
            visibleArea = new System.Drawing.RectangleF(0, 0, this.screenDimensions.X, this.screenDimensions.Y);
            position = ScreenPosition;
        }
        public Camera2D(Vector2 MaxDimensions,float width, float height)
        {
            this.screenDimensions = MaxDimensions;
            visibleArea = new System.Drawing.RectangleF(0, 0, width, height);
            position = ScreenPosition;
        }
        public Camera2D(Vector2 MaxDimensions,float x, float y, float width, float height)
        {
            this.screenDimensions = MaxDimensions;
            visibleArea = new System.Drawing.RectangleF(x - (width / 2), y - (height / 2), width, height);
            position.X = x;
            position.Y = y;
        }

        public void Dispose()
        {
            //visibleArea = null;

            // Clear out event handlers
            //PositionChanged = null;
            //Teleported = null;
            //Moved = null;
        }

        ///
        /// Returns a transformation matrix based on the camera’s position, rotation, and zoom.
        /// Best used as a parameter for the SpriteBatch.Begin() call.
        ///
        public virtual Matrix ViewTransformationMatrix()
        {
            Vector3 matrixRotOrigin = new Vector3(Position + Offset, 0);
            Vector3 matrixScreenPos = new Vector3(ScreenPosition, 0.0f);

            // Translate back to the origin based on the camera’s offset position, since we’re rotating around the camera
            // Then, we scale and rotate around the origin
            // Finally, we translate to SCREEN coordinates, so translation is based on the ScreenCenter
            return Matrix.CreateTranslation(-matrixRotOrigin) *
                Matrix.CreateScale(this.Zoom.X, this.Zoom.Y, 1.0f) *
                Matrix.CreateRotationZ(this.Rotation) *
                Matrix.CreateTranslation(matrixScreenPos);
        }
    }
}
